#!/usr/bin/env python3
"""
智慧农业边缘控制系统 - 完整Web演示版本
Smart Agriculture Edge Control System - Complete Web Demo

功能特点：
- 完整的智慧农业功能演示
- 真实的数据模拟和趋势分析
- 丰富的交互功能和可视化
- 专业级的用户界面设计
"""

from flask import Flask, render_template_string, jsonify, request
import json
import random
from datetime import datetime, timedelta
import threading
import time
import socket
import numpy as np
from collections import deque
import math
import sqlite3
import os

class AdvancedAgriculturalSystem:
    """高级智慧农业系统"""
    
    def __init__(self):
        # 数据缓冲区 - 不同时间维度
        self.realtime_data = deque(maxlen=60)      # 实时数据(2分钟)
        self.hourly_data = deque(maxlen=24)        # 小时数据(24小时)
        self.daily_data = deque(maxlen=30)         # 日数据(30天)
        self.weekly_data = deque(maxlen=52)        # 周数据(52周)
        
        # 当前传感器数据
        self.current_data = {
            'timestamp': datetime.now().isoformat(),
            'soil_moisture': 45.0,
            'air_temperature': 25.0,
            'air_humidity': 60.0,
            'light_intensity': 40000.0,
            'ph_value': 6.8,
            'nitrogen': 25.0,
            'phosphorus': 15.0,
            'potassium': 30.0,
            'co2_level': 400.0,
            'soil_temperature': 22.0,
            'wind_speed': 3.0,
            'atmospheric_pressure': 1013.25,
            'rainfall': 0.0,
            'uv_index': 5.0,
            'soil_conductivity': 1.2
        }
        
        # 系统状态
        self.irrigation_zones = {
            'zone_a': {'name': '区域A', 'active': False, 'flow_rate': 0, 'last_irrigation': None},
            'zone_b': {'name': '区域B', 'active': False, 'flow_rate': 0, 'last_irrigation': None},
            'zone_c': {'name': '区域C', 'active': False, 'flow_rate': 0, 'last_irrigation': None},
            'zone_d': {'name': '区域D', 'active': False, 'flow_rate': 0, 'last_irrigation': None}
        }
        
        self.auto_irrigation = True
        self.irrigation_threshold = 30.0
        
        # 设备状态
        self.devices = {
            'sensors': {'active': 12, 'total': 15, 'status': 'normal'},
            'pumps': {'active': 3, 'total': 4, 'status': 'normal'},
            'valves': {'active': 8, 'total': 8, 'status': 'normal'},
            'weather_station': {'active': 1, 'total': 1, 'status': 'normal'}
        }
        
        # AI分析结果
        self.ai_analysis = {
            'pest_risk': 'low',
            'disease_risk': 'medium',
            'yield_prediction': 8.5,
            'optimization_score': 85,
            'last_analysis': datetime.now().isoformat()
        }
        
        # 天气模式
        self.weather_pattern = random.choice(['sunny', 'cloudy', 'rainy', 'windy'])
        self.season_factor = self._get_season_factor()
        
        # 警报系统
        self.alerts = deque(maxlen=50)
        
        # 启动数据生成
        self.running = True
        self._init_historical_data()
        self.start_data_generation()
    
    def _get_season_factor(self):
        """获取季节因子"""
        month = datetime.now().month
        if month in [3, 4, 5]:  # 春季
            return {'temp_offset': 0, 'humidity_offset': 10, 'light_factor': 1.05}
        elif month in [6, 7, 8]:  # 夏季
            return {'temp_offset': 8, 'humidity_offset': -10, 'light_factor': 1.15}
        elif month in [9, 10, 11]:  # 秋季
            return {'temp_offset': -2, 'humidity_offset': 5, 'light_factor': 0.95}
        else:  # 冬季
            return {'temp_offset': -8, 'humidity_offset': 15, 'light_factor': 0.80}
    
    def _init_historical_data(self):
        """初始化历史数据"""
        # 生成过去24小时数据
        for i in range(24):
            timestamp = datetime.now() - timedelta(hours=23-i)
            data = self._generate_realistic_data(timestamp)
            self.hourly_data.append(data)
        
        # 生成过去30天数据
        for i in range(30):
            timestamp = datetime.now() - timedelta(days=29-i)
            data = self._generate_realistic_data(timestamp, time_scale='daily')
            self.daily_data.append(data)
    
    def _generate_realistic_data(self, timestamp, time_scale='hourly'):
        """生成真实的传感器数据"""
        hour = timestamp.hour
        day_of_year = timestamp.timetuple().tm_yday
        
        # 日循环因子
        day_factor = max(0, 0.5 + 0.5 * math.sin((hour - 6) * math.pi / 12))
        
        # 年循环因子（季节变化）
        year_factor = 0.5 + 0.5 * math.sin((day_of_year - 80) * 2 * math.pi / 365)
        
        # 天气影响
        weather_effects = self._get_weather_effects()
        
        data = {
            'timestamp': timestamp.isoformat(),
            'soil_moisture': self._generate_soil_moisture(day_factor, weather_effects),
            'air_temperature': self._generate_temperature(day_factor, year_factor, weather_effects),
            'air_humidity': self._generate_humidity(day_factor, weather_effects),
            'light_intensity': self._generate_light(day_factor, weather_effects),
            'ph_value': self._generate_ph(weather_effects),
            'nitrogen': self._generate_nutrient('nitrogen'),
            'phosphorus': self._generate_nutrient('phosphorus'),
            'potassium': self._generate_nutrient('potassium'),
            'co2_level': self._generate_co2(day_factor),
            'soil_temperature': self._generate_soil_temp(day_factor, year_factor),
            'wind_speed': self._generate_wind(weather_effects),
            'atmospheric_pressure': self._generate_pressure(weather_effects),
            'rainfall': weather_effects.get('rainfall', 0) * 10,
            'uv_index': self._generate_uv(day_factor, weather_effects),
            'soil_conductivity': self._generate_conductivity()
        }
        
        return data
    
    def _generate_soil_moisture(self, day_factor, weather_effects):
        """生成土壤湿度数据"""
        base_moisture = 45.0
        daily_variation = -8 * day_factor  # 白天蒸发更快
        weather_impact = weather_effects.get('rainfall', 0) * 20
        irrigation_impact = self._get_irrigation_impact()
        random_noise = random.uniform(-2, 1)
        
        moisture = base_moisture + daily_variation + weather_impact + irrigation_impact + random_noise
        return max(15, min(85, moisture))
    
    def _get_irrigation_impact(self):
        """获取灌溉影响"""
        active_zones = sum(1 for zone in self.irrigation_zones.values() if zone['active'])
        return active_zones * 3  # 每个活跃区域增加3%湿度
    
    def _generate_temperature(self, day_factor, year_factor, weather_effects):
        """生成温度数据"""
        base_temp = 18.0 + self.season_factor['temp_offset']
        daily_variation = 14 * day_factor
        weather_impact = weather_effects.get('cloud_cover', 0.3) * -6
        random_noise = random.uniform(-1.5, 1.5)
        
        temp = base_temp + daily_variation + weather_impact + random_noise
        return max(5, min(45, temp))
    
    def _generate_humidity(self, day_factor, weather_effects):
        """生成湿度数据"""
        base_humidity = 75.0 + self.season_factor['humidity_offset']
        daily_variation = -30 * day_factor
        weather_impact = weather_effects.get('rainfall', 0) * 25
        random_noise = random.uniform(-8, 8)
        
        humidity = base_humidity + daily_variation + weather_impact + random_noise
        return max(20, min(95, humidity))
    
    def _generate_light(self, day_factor, weather_effects):
        """生成光照强度数据"""
        max_light = 75000 * self.season_factor['light_factor']
        cloud_reduction = 1 - weather_effects.get('cloud_cover', 0.2)
        random_factor = random.uniform(0.85, 1.15)
        
        light = max_light * day_factor * cloud_reduction * random_factor
        return max(0, light)
    
    def _generate_ph(self, weather_effects):
        """生成pH值数据"""
        base_ph = 6.8
        rain_impact = weather_effects.get('rainfall', 0) * -0.3
        fertilizer_impact = random.uniform(-0.1, 0.2)  # 模拟施肥影响
        
        ph = base_ph + rain_impact + fertilizer_impact
        return max(5.5, min(8.5, ph))
    
    def _generate_nutrient(self, nutrient_type):
        """生成营养元素数据"""
        base_values = {'nitrogen': 25, 'phosphorus': 15, 'potassium': 30}
        base = base_values[nutrient_type]
        
        consumption = random.uniform(-0.8, 0.2)  # 植物吸收
        fertilizer_add = random.uniform(0, 0.5) if random.random() < 0.1 else 0  # 10%概率施肥
        
        value = base + consumption + fertilizer_add
        return max(5, min(50, value))
    
    def _generate_co2(self, day_factor):
        """生成CO2浓度数据"""
        base_co2 = 400
        daily_variation = -60 * day_factor  # 白天植物吸收CO2
        random_noise = random.uniform(-20, 20)
        
        co2 = base_co2 + daily_variation + random_noise
        return max(300, min(600, co2))
    
    def _generate_soil_temp(self, day_factor, year_factor):
        """生成土壤温度数据"""
        base_temp = 16.0 + self.season_factor['temp_offset'] * 0.7
        daily_variation = 6 * day_factor  # 土壤温度变化较小
        random_noise = random.uniform(-0.8, 0.8)
        
        temp = base_temp + daily_variation + random_noise
        return max(5, min(35, temp))
    
    def _generate_wind(self, weather_effects):
        """生成风速数据"""
        base_wind = 2.5
        weather_boost = weather_effects.get('storm_factor', 0) * 10
        random_variation = random.uniform(-1, 4)
        
        wind = base_wind + weather_boost + random_variation
        return max(0, min(20, wind))
    
    def _generate_pressure(self, weather_effects):
        """生成大气压数据"""
        base_pressure = 1013.25
        weather_variation = weather_effects.get('pressure_change', 0) * 25
        random_noise = random.uniform(-8, 8)
        
        pressure = base_pressure + weather_variation + random_noise
        return max(980, min(1040, pressure))
    
    def _generate_uv(self, day_factor, weather_effects):
        """生成紫外线指数"""
        max_uv = 11
        cloud_reduction = 1 - weather_effects.get('cloud_cover', 0.2) * 0.7
        seasonal_factor = self.season_factor['light_factor']
        
        uv = max_uv * day_factor * cloud_reduction * seasonal_factor
        return max(0, min(11, uv))
    
    def _generate_conductivity(self):
        """生成土壤电导率"""
        base_conductivity = 1.2
        variation = random.uniform(-0.3, 0.3)
        return max(0.5, min(3.0, base_conductivity + variation))
    
    def _get_weather_effects(self):
        """获取天气影响因子"""
        if not hasattr(self, '_weather_cache') or random.random() < 0.05:
            self._weather_cache = {
                'rainfall': random.choice([0, 0, 0, 0, 0.2, 0.5, 0.8, 1.0]),
                'cloud_cover': random.uniform(0.1, 0.9),
                'storm_factor': random.choice([0, 0, 0, 0, 0, 0.3, 0.7, 1.0]),
                'pressure_change': random.uniform(-1, 1)
            }
        return self._weather_cache
    
    def start_data_generation(self):
        """启动数据生成线程"""
        def generate_data():
            while self.running:
                try:
                    # 生成新数据
                    new_data = self._generate_realistic_data(datetime.now())
                    self.current_data = new_data
                    
                    # 添加到实时数据缓冲区
                    self.realtime_data.append(new_data)
                    
                    # 每小时添加到小时数据
                    if datetime.now().minute == 0:
                        self.hourly_data.append(new_data)
                    
                    # 检查警报条件
                    self._check_alerts()
                    
                    # 自动灌溉逻辑
                    self._auto_irrigation_check()
                    
                    # 更新AI分析
                    if random.random() < 0.1:  # 10%概率更新AI分析
                        self._update_ai_analysis()
                    
                    time.sleep(2)  # 每2秒更新一次
                    
                except Exception as e:
                    print(f"数据生成错误: {e}")
                    time.sleep(5)
        
        thread = threading.Thread(target=generate_data, daemon=True)
        thread.start()
    
    def _check_alerts(self):
        """检查警报条件"""
        current_time = datetime.now()
        
        # 土壤湿度警报
        if self.current_data['soil_moisture'] < 25:
            self._add_alert('error', '土壤湿度过低', f"当前湿度: {self.current_data['soil_moisture']:.1f}%，建议立即灌溉")
        elif self.current_data['soil_moisture'] > 80:
            self._add_alert('warning', '土壤湿度过高', f"当前湿度: {self.current_data['soil_moisture']:.1f}%，可能导致根部缺氧")
        
        # 温度警报
        if self.current_data['air_temperature'] > 35:
            self._add_alert('error', '温度过高', f"当前温度: {self.current_data['air_temperature']:.1f}°C，植物面临热胁迫")
        elif self.current_data['air_temperature'] < 10:
            self._add_alert('warning', '温度过低', f"当前温度: {self.current_data['air_temperature']:.1f}°C，植物生长受阻")
        
        # pH值警报
        if self.current_data['ph_value'] < 6.0 or self.current_data['ph_value'] > 8.0:
            self._add_alert('warning', 'pH值异常', f"当前pH: {self.current_data['ph_value']:.1f}，影响营养吸收")
        
        # 设备状态警报
        if random.random() < 0.001:  # 0.1%概率设备故障
            device = random.choice(['传感器', '水泵', '阀门'])
            self._add_alert('error', f'{device}故障', f'{device}离线，请检查设备状态')
    
    def _add_alert(self, level, title, message):
        """添加警报"""
        alert = {
            'id': len(self.alerts) + 1,
            'level': level,
            'title': title,
            'message': message,
            'timestamp': datetime.now().isoformat(),
            'acknowledged': False
        }
        self.alerts.append(alert)
    
    def _auto_irrigation_check(self):
        """自动灌溉检查"""
        if not self.auto_irrigation:
            return
        
        if self.current_data['soil_moisture'] < self.irrigation_threshold:
            # 启动需要灌溉的区域
            for zone_id, zone in self.irrigation_zones.items():
                if not zone['active'] and random.random() < 0.3:  # 30%概率启动
                    zone['active'] = True
                    zone['flow_rate'] = random.uniform(5, 15)
                    zone['last_irrigation'] = datetime.now().isoformat()
                    self._add_alert('info', '自动灌溉启动', f"{zone['name']}开始灌溉")
        
        # 停止已运行足够时间的区域
        for zone_id, zone in self.irrigation_zones.items():
            if zone['active'] and zone['last_irrigation']:
                start_time = datetime.fromisoformat(zone['last_irrigation'])
                if (datetime.now() - start_time).seconds > 300:  # 5分钟后停止
                    zone['active'] = False
                    zone['flow_rate'] = 0
                    self._add_alert('info', '自动灌溉停止', f"{zone['name']}灌溉完成")
    
    def _update_ai_analysis(self):
        """更新AI分析结果"""
        # 病虫害风险评估
        risk_factors = [
            self.current_data['air_humidity'] > 80,  # 高湿度增加病害风险
            self.current_data['air_temperature'] > 30,  # 高温增加虫害风险
            self.current_data['soil_moisture'] > 75,  # 过湿增加真菌风险
        ]
        
        if sum(risk_factors) >= 2:
            self.ai_analysis['pest_risk'] = 'high'
            self.ai_analysis['disease_risk'] = 'high'
        elif sum(risk_factors) == 1:
            self.ai_analysis['pest_risk'] = 'medium'
            self.ai_analysis['disease_risk'] = 'medium'
        else:
            self.ai_analysis['pest_risk'] = 'low'
            self.ai_analysis['disease_risk'] = 'low'
        
        # 产量预测（基于环境条件）
        optimal_temp = 25
        optimal_humidity = 65
        optimal_moisture = 55
        
        temp_score = 1 - abs(self.current_data['air_temperature'] - optimal_temp) / 20
        humidity_score = 1 - abs(self.current_data['air_humidity'] - optimal_humidity) / 40
        moisture_score = 1 - abs(self.current_data['soil_moisture'] - optimal_moisture) / 30
        
        overall_score = (temp_score + humidity_score + moisture_score) / 3
        self.ai_analysis['yield_prediction'] = max(3.0, min(10.0, overall_score * 10))
        self.ai_analysis['optimization_score'] = int(overall_score * 100)
        self.ai_analysis['last_analysis'] = datetime.now().isoformat()
    
    def get_current_data(self):
        """获取当前数据"""
        return self.current_data
    
    def get_historical_data(self, time_scale='realtime', limit=None):
        """获取历史数据"""
        if time_scale == 'realtime':
            data = list(self.realtime_data)
        elif time_scale == 'hourly':
            data = list(self.hourly_data)
        elif time_scale == 'daily':
            data = list(self.daily_data)
        else:
            data = list(self.realtime_data)
        
        if limit:
            data = data[-limit:]
        
        return data
    
    def get_system_status(self):
        """获取系统状态"""
        return {
            'irrigation_zones': self.irrigation_zones,
            'auto_irrigation': self.auto_irrigation,
            'irrigation_threshold': self.irrigation_threshold,
            'devices': self.devices,
            'ai_analysis': self.ai_analysis,
            'weather_pattern': self.weather_pattern,
            'alerts': list(self.alerts)[-10:],  # 最近10个警报
            'system_uptime': 'Online',
            'data_quality': 'Excellent'
        }
    
    def control_irrigation(self, zone_id, action):
        """控制灌溉"""
        if zone_id in self.irrigation_zones:
            if action == 'start':
                self.irrigation_zones[zone_id]['active'] = True
                self.irrigation_zones[zone_id]['flow_rate'] = random.uniform(8, 12)
                self.irrigation_zones[zone_id]['last_irrigation'] = datetime.now().isoformat()
                return {'success': True, 'message': f"{self.irrigation_zones[zone_id]['name']}灌溉已启动"}
            elif action == 'stop':
                self.irrigation_zones[zone_id]['active'] = False
                self.irrigation_zones[zone_id]['flow_rate'] = 0
                return {'success': True, 'message': f"{self.irrigation_zones[zone_id]['name']}灌溉已停止"}
        
        return {'success': False, 'message': '操作失败'}
    
    def set_auto_irrigation(self, enabled, threshold=None):
        """设置自动灌溉"""
        self.auto_irrigation = enabled
        if threshold:
            self.irrigation_threshold = threshold
        
        return {'success': True, 'message': f"自动灌溉已{'启用' if enabled else '禁用'}"}

# 创建全局系统实例
agricultural_system = AdvancedAgriculturalSystem()

# Flask应用
app = Flask(__name__)

def find_available_port(start_port=8080):
    """找到可用端口"""
    for port in range(start_port, start_port + 50):
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                s.bind(('', port))
                return port
        except OSError:
            continue
    return 8080

# 主页面HTML模板
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>🌱 智慧农业边缘控制系统</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/date-fns@2.29.3/index.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #e8f5e8 0%, #f0f8ff 100%);
            min-height: 100vh;
            color: #333;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }
        
        .header {
            background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
            color: white;
            padding: 30px 20px;
            border-radius: 15px;
            margin-bottom: 30px;
            text-align: center;
            box-shadow: 0 8px 20px rgba(76, 175, 80, 0.3);
        }
        
        .header h1 {
            font-size: 2.8em;
            margin-bottom: 10px;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
        }
        
        .header p {
            font-size: 1.2em;
            opacity: 0.9;
        }
        
        .status-bar {
            background: rgba(255,255,255,0.95);
            padding: 15px 30px;
            border-radius: 50px;
            margin: 20px 0;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        }
        
        .status-item {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .status-indicator {
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: #4CAF50;
            animation: pulse 2s infinite;
        }
        
        @keyframes pulse {
            0% { opacity: 1; }
            50% { opacity: 0.5; }
            100% { opacity: 1; }
        }
        
        .dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
            gap: 25px;
            margin-bottom: 30px;
        }
        
        .card {
            background: rgba(255,255,255,0.95);
            border-radius: 20px;
            padding: 25px;
            box-shadow: 0 8px 25px rgba(0,0,0,0.1);
            transition: transform 0.3s ease, box-shadow 0.3s ease;
            border: 1px solid rgba(76, 175, 80, 0.2);
        }
        
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 15px 35px rgba(0,0,0,0.15);
        }
        
        .card-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #f0f0f0;
        }
        
        .card-title {
            font-size: 1.4em;
            font-weight: bold;
            color: #2e7d32;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .sensor-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: 15px;
        }
        
        .sensor-item {
            background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
            padding: 20px;
            border-radius: 15px;
            text-align: center;
            border: 2px solid transparent;
            transition: all 0.3s ease;
        }
        
        .sensor-item:hover {
            border-color: #4CAF50;
            transform: scale(1.05);
        }
        
        .sensor-icon {
            font-size: 2em;
            margin-bottom: 10px;
        }
        
        .sensor-value {
            font-size: 1.8em;
            font-weight: bold;
            color: #2e7d32;
            margin-bottom: 5px;
        }
        
        .sensor-label {
            color: #666;
            font-size: 0.9em;
            font-weight: 500;
        }
        
        .chart-container {
            position: relative;
            height: 350px;
            margin-top: 20px;
        }
        
        .chart-controls {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
            flex-wrap: wrap;
        }
        
        .btn {
            background: #4CAF50;
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 25px;
            cursor: pointer;
            font-size: 1em;
            font-weight: 500;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .btn:hover {
            background: #45a049;
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(76, 175, 80, 0.4);
        }
        
        .btn-secondary {
            background: #2196F3;
        }
        
        .btn-secondary:hover {
            background: #1976D2;
        }
        
        .btn-warning {
            background: #FF9800;
        }
        
        .btn-warning:hover {
            background: #F57C00;
        }
        
        .btn-danger {
            background: #f44336;
        }
        
        .btn-danger:hover {
            background: #d32f2f;
        }
        
        .irrigation-zone {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 10px;
            margin-bottom: 10px;
            border-left: 4px solid #4CAF50;
        }
        
        .zone-info {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        .zone-status {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: #ccc;
        }
        
        .zone-status.active {
            background: #4CAF50;
            animation: pulse 1.5s infinite;
        }
        
        .alerts-container {
            max-height: 300px;
            overflow-y: auto;
        }
        
        .alert {
            padding: 15px;
            border-radius: 10px;
            margin-bottom: 10px;
            display: flex;
            align-items: center;
            gap: 15px;
        }
        
        .alert-info {
            background: #e3f2fd;
            border-left: 4px solid #2196F3;
        }
        
        .alert-warning {
            background: #fff3e0;
            border-left: 4px solid #FF9800;
        }
        
        .alert-error {
            background: #ffebee;
            border-left: 4px solid #f44336;
        }
        
        .ai-result {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin-top: 20px;
        }
        
        .ai-metric {
            text-align: center;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 15px;
            border: 2px solid transparent;
            transition: all 0.3s ease;
        }
        
        .ai-metric:hover {
            border-color: #9C27B0;
        }
        
        .ai-value {
            font-size: 2em;
            font-weight: bold;
            color: #9C27B0;
            margin-bottom: 5px;
        }
        
        .progress-bar {
            width: 100%;
            height: 8px;
            background: #e0e0e0;
            border-radius: 4px;
            overflow: hidden;
            margin-top: 10px;
        }
        
        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, #4CAF50, #8BC34A);
            border-radius: 4px;
            transition: width 0.5s ease;
        }
        
        .footer {
            text-align: center;
            padding: 30px;
            background: rgba(255,255,255,0.8);
            border-radius: 15px;
            margin-top: 30px;
            color: #666;
        }
        
        @media (max-width: 768px) {
            .container {
                padding: 10px;
            }
            
            .dashboard {
                grid-template-columns: 1fr;
            }
            
            .header h1 {
                font-size: 2em;
            }
            
            .status-bar {
                flex-direction: column;
                gap: 10px;
            }
        }
        
        .loading {
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid #f3f3f3;
            border-top: 3px solid #4CAF50;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <div class="container">
        <!-- 头部 -->
        <div class="header">
            <h1>🌱 智慧农业边缘控制系统</h1>
            <p>Smart Agriculture Edge Control System - Complete Demo</p>
        </div>
        
        <!-- 状态栏 -->
        <div class="status-bar">
            <div class="status-item">
                <div class="status-indicator"></div>
                <span>系统运行正常</span>
            </div>
            <div class="status-item">
                <span>📡 传感器: <span id="sensor-count">15/15</span></span>
            </div>
            <div class="status-item">
                <span>💧 灌溉系统: <span id="irrigation-status">自动模式</span></span>
            </div>
            <div class="status-item">
                <span>🕒 最后更新: <span id="last-update">--</span></span>
            </div>
        </div>
        
        <!-- 主仪表板 -->
        <div class="dashboard">
            <!-- 传感器数据卡片 -->
            <div class="card">
                <div class="card-header">
                    <h3 class="card-title">📊 环境监控</h3>
                    <button class="btn btn-secondary" onclick="refreshSensorData()">
                        <span>🔄</span> 刷新
                    </button>
                </div>
                <div class="sensor-grid" id="sensor-display">
                    <!-- 传感器数据将在这里动态加载 -->
                </div>
            </div>
            
            <!-- 实时图表 -->
            <div class="card">
                <div class="card-header">
                    <h3 class="card-title">📈 数据趋势</h3>
                    <div class="chart-controls">
                        <select id="time-scale" onchange="updateChart()">
                            <option value="realtime">实时(2分钟)</option>
                            <option value="hourly">小时(24小时)</option>
                            <option value="daily">日(30天)</option>
                        </select>
                        <select id="chart-type" onchange="updateChart()">
                            <option value="line">线性图</option>
                            <option value="bar">柱状图</option>
                        </select>
                    </div>
                </div>
                <div class="chart-container">
                    <canvas id="trendChart"></canvas>
                </div>
            </div>
            
            <!-- 灌溉控制 -->
            <div class="card">
                <div class="card-header">
                    <h3 class="card-title">💧 灌溉控制</h3>
                    <div>
                        <button class="btn" onclick="toggleAutoIrrigation()">
                            <span id="auto-btn-icon">🔄</span>
                            <span id="auto-btn-text">自动模式</span>
                        </button>
                    </div>
                </div>
                
                <div style="margin-bottom: 20px;">
                    <label>湿度阈值: </label>
                    <input type="range" id="threshold-slider" min="20" max="60" value="30" 
                           onchange="updateThreshold(this.value)">
                    <span id="threshold-value">30%</span>
                </div>
                
                <div id="irrigation-zones">
                    <!-- 灌溉区域将在这里动态加载 -->
                </div>
            </div>
            
            <!-- AI智能分析 -->
            <div class="card">
                <div class="card-header">
                    <h3 class="card-title">🤖 AI智能分析</h3>
                    <button class="btn btn-warning" onclick="runAIAnalysis()">
                        <span id="ai-btn-icon">🔍</span>
                        <span id="ai-btn-text">执行分析</span>
                    </button>
                </div>
                
                <div class="ai-result" id="ai-results">
                    <!-- AI分析结果将在这里显示 -->
                </div>
            </div>
            
            <!-- 系统状态 -->
            <div class="card">
                <div class="card-header">
                    <h3 class="card-title">⚙️ 设备状态</h3>
                    <button class="btn btn-secondary" onclick="refreshDeviceStatus()">
                        <span>📊</span> 检查
                    </button>
                </div>
                
                <div id="device-status">
                    <!-- 设备状态将在这里显示 -->
                </div>
            </div>
            
            <!-- 系统警报 -->
            <div class="card">
                <div class="card-header">
                    <h3 class="card-title">🚨 系统警报</h3>
                    <button class="btn btn-danger" onclick="clearAlerts()">
                        <span>🧹</span> 清空
                    </button>
                </div>
                
                <div class="alerts-container" id="alerts-display">
                    <!-- 警报将在这里显示 -->
                </div>
            </div>
        </div>
        
        <!-- 底部 -->
        <div class="footer">
            <p>🌱 智慧农业边缘控制系统 v4.3 | 数据每2秒自动更新 | 
            <button class="btn btn-secondary" onclick="exportData()" style="margin-left: 10px;">
                📊 导出数据
            </button>
            </p>
        </div>
    </div>

    <script>
        let chart = null;
        let updateInterval = null;
        let autoIrrigation = true;
        
        // 传感器配置
        const sensorConfig = {
            'soil_moisture': { icon: '🌱', name: '土壤湿度', unit: '%', color: '#4CAF50' },
            'air_temperature': { icon: '🌡️', name: '空气温度', unit: '°C', color: '#FF6347' },
            'air_humidity': { icon: '💧', name: '空气湿度', unit: '%', color: '#2196F3' },
            'light_intensity': { icon: '☀️', name: '光照强度', unit: 'lux', color: '#FFD700' },
            'ph_value': { icon: '⚗️', name: 'pH值', unit: '', color: '#9C27B0' },
            'nitrogen': { icon: '🧪', name: '氮含量', unit: 'ppm', color: '#00BCD4' },
            'phosphorus': { icon: '🔬', name: '磷含量', unit: 'ppm', color: '#E91E63' },
            'potassium': { icon: '⚡', name: '钾含量', unit: 'ppm', color: '#8BC34A' },
            'co2_level': { icon: '🌬️', name: 'CO2浓度', unit: 'ppm', color: '#795548' },
            'wind_speed': { icon: '💨', name: '风速', unit: 'm/s', color: '#607D8B' }
        };
        
        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            initializeChart();
            startAutoUpdate();
            updateSensorData();
            updateSystemStatus();
        });
        
        // 初始化图表
        function initializeChart() {
            const ctx = document.getElementById('trendChart').getContext('2d');
            chart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: [],
                    datasets: [
                        {
                            label: '土壤湿度 (%)',
                            data: [],
                            borderColor: '#4CAF50',
                            backgroundColor: 'rgba(76, 175, 80, 0.1)',
                            tension: 0.4
                        },
                        {
                            label: '空气温度 (°C)',
                            data: [],
                            borderColor: '#FF6347',
                            backgroundColor: 'rgba(255, 99, 71, 0.1)',
                            tension: 0.4
                        },
                        {
                            label: '空气湿度 (%)',
                            data: [],
                            borderColor: '#2196F3',
                            backgroundColor: 'rgba(33, 150, 243, 0.1)',
                            tension: 0.4
                        }
                    ]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            position: 'top',
                        }
                    },
                    scales: {
                        y: {
                            beginAtZero: true,
                            grid: {
                                color: 'rgba(0,0,0,0.1)'
                            }
                        },
                        x: {
                            grid: {
                                color: 'rgba(0,0,0,0.1)'
                            }
                        }
                    },
                    animation: {
                        duration: 1000
                    }
                }
            });
        }
        
        // 启动自动更新
        function startAutoUpdate() {
            updateInterval = setInterval(() => {
                updateSensorData();
                updateSystemStatus();
                updateChart();
            }, 2000);
        }
        
        // 更新传感器数据
        function updateSensorData() {
            fetch('/api/current-data')
                .then(response => response.json())
                .then(data => {
                    const container = document.getElementById('sensor-display');
                    container.innerHTML = '';
                    
                    Object.entries(sensorConfig).forEach(([key, config]) => {
                        if (data[key] !== undefined) {
                            const value = typeof data[key] === 'number' ? data[key].toFixed(1) : data[key];
                            
                            const sensorItem = document.createElement('div');
                            sensorItem.className = 'sensor-item';
                            sensorItem.innerHTML = `
                                <div class="sensor-icon">${config.icon}</div>
                                <div class="sensor-value" style="color: ${config.color}">${value}</div>
                                <div class="sensor-label">${config.name} ${config.unit}</div>
                            `;
                            container.appendChild(sensorItem);
                        }
                    });
                    
                    // 更新最后更新时间
                    document.getElementById('last-update').textContent = 
                        new Date().toLocaleTimeString();
                })
                .catch(error => {
                    console.error('数据更新失败:', error);
                });
        }
        
        // 更新系统状态
        function updateSystemStatus() {
            fetch('/api/system-status')
                .then(response => response.json())
                .then(data => {
                    // 更新灌溉区域
                    updateIrrigationZones(data.irrigation_zones);
                    
                    // 更新AI分析结果
                    updateAIResults(data.ai_analysis);
                    
                    // 更新设备状态
                    updateDeviceStatus(data.devices);
                    
                    // 更新警报
                    updateAlerts(data.alerts);
                    
                    // 更新状态栏
                    const activeDevices = Object.values(data.devices)
                        .reduce((sum, device) => sum + device.active, 0);
                    const totalDevices = Object.values(data.devices)
                        .reduce((sum, device) => sum + device.total, 0);
                    
                    document.getElementById('sensor-count').textContent = 
                        `${activeDevices}/${totalDevices}`;
                    
                    document.getElementById('irrigation-status').textContent = 
                        data.auto_irrigation ? '自动模式' : '手动模式';
                })
                .catch(error => {
                    console.error('状态更新失败:', error);
                });
        }
        
        // 更新图表
        function updateChart() {
            const timeScale = document.getElementById('time-scale').value;
            const chartType = document.getElementById('chart-type').value;
            
            fetch(`/api/historical-data?time_scale=${timeScale}&limit=20`)
                .then(response => response.json())
                .then(data => {
                    if (data.length === 0) return;
                    
                    const labels = data.map(item => {
                        const date = new Date(item.timestamp);
                        if (timeScale === 'realtime') {
                            return date.toLocaleTimeString();
                        } else if (timeScale === 'hourly') {
                            return date.toLocaleString();
                        } else {
                            return date.toLocaleDateString();
                        }
                    });
                    
                    chart.data.labels = labels;
                    chart.data.datasets[0].data = data.map(item => item.soil_moisture);
                    chart.data.datasets[1].data = data.map(item => item.air_temperature);
                    chart.data.datasets[2].data = data.map(item => item.air_humidity);
                    
                    chart.config.type = chartType;
                    chart.update('none');
                })
                .catch(error => {
                    console.error('图表更新失败:', error);
                });
        }
        
        // 更新灌溉区域
        function updateIrrigationZones(zones) {
            const container = document.getElementById('irrigation-zones');
            container.innerHTML = '';
            
            Object.entries(zones).forEach(([zoneId, zone]) => {
                const zoneDiv = document.createElement('div');
                zoneDiv.className = 'irrigation-zone';
                zoneDiv.innerHTML = `
                    <div class="zone-info">
                        <div class="zone-status ${zone.active ? 'active' : ''}"></div>
                        <span style="font-weight: bold;">${zone.name}</span>
                        <span style="color: #666;">
                            ${zone.active ? `流量: ${zone.flow_rate.toFixed(1)} L/min` : '停止'}
                        </span>
                    </div>
                    <div>
                        <button class="btn ${zone.active ? 'btn-danger' : ''}" 
                                onclick="toggleZone('${zoneId}', ${!zone.active})">
                            ${zone.active ? '⏹️ 停止' : '▶️ 启动'}
                        </button>
                    </div>
                `;
                container.appendChild(zoneDiv);
            });
        }
        
        // 更新AI分析结果
        function updateAIResults(aiData) {
            const container = document.getElementById('ai-results');
            
            const riskColors = {
                'low': '#4CAF50',
                'medium': '#FF9800', 
                'high': '#f44336'
            };
            
            container.innerHTML = `
                <div class="ai-metric">
                    <div class="ai-value" style="color: ${riskColors[aiData.pest_risk]}">
                        ${aiData.pest_risk.toUpperCase()}
                    </div>
                    <div>病虫害风险</div>
                </div>
                <div class="ai-metric">
                    <div class="ai-value" style="color: ${riskColors[aiData.disease_risk]}">
                        ${aiData.disease_risk.toUpperCase()}
                    </div>
                    <div>病害风险</div>
                </div>
                <div class="ai-metric">
                    <div class="ai-value">${aiData.yield_prediction.toFixed(1)}</div>
                    <div>预测产量 (吨/亩)</div>
                </div>
                <div class="ai-metric">
                    <div class="ai-value">${aiData.optimization_score}%</div>
                    <div>优化评分</div>
                    <div class="progress-bar">
                        <div class="progress-fill" style="width: ${aiData.optimization_score}%"></div>
                    </div>
                </div>
            `;
        }
        
        // 更新设备状态
        function updateDeviceStatus(devices) {
            const container = document.getElementById('device-status');
            container.innerHTML = '';
            
            const deviceNames = {
                'sensors': '📡 传感器',
                'pumps': '💧 水泵',
                'valves': '🔧 阀门',
                'weather_station': '🌤️ 气象站'
            };
            
            Object.entries(devices).forEach(([deviceType, device]) => {
                const percentage = (device.active / device.total * 100).toFixed(0);
                const statusColor = device.status === 'normal' ? '#4CAF50' : '#f44336';
                
                const deviceDiv = document.createElement('div');
                deviceDiv.innerHTML = `
                    <div style="display: flex; justify-content: space-between; align-items: center; 
                                padding: 10px; background: #f8f9fa; border-radius: 8px; margin-bottom: 8px;">
                        <span>${deviceNames[deviceType]}</span>
                        <span style="color: ${statusColor}; font-weight: bold;">
                            ${device.active}/${device.total} (${percentage}%)
                        </span>
                    </div>
                `;
                container.appendChild(deviceDiv);
            });
        }
        
        // 更新警报
        function updateAlerts(alerts) {
            const container = document.getElementById('alerts-display');
            container.innerHTML = '';
            
            if (alerts.length === 0) {
                container.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">暂无警报</div>';
                return;
            }
            
            alerts.reverse().forEach(alert => {
                const alertDiv = document.createElement('div');
                alertDiv.className = `alert alert-${alert.level}`;
                
                const icons = {
                    'info': 'ℹ️',
                    'warning': '⚠️',
                    'error': '🚨'
                };
                
                const time = new Date(alert.timestamp).toLocaleTimeString();
                
                alertDiv.innerHTML = `
                    <div style="font-size: 1.2em;">${icons[alert.level]}</div>
                    <div style="flex: 1;">
                        <div style="font-weight: bold;">${alert.title}</div>
                        <div style="font-size: 0.9em; color: #666;">${alert.message}</div>
                        <div style="font-size: 0.8em; color: #999; margin-top: 5px;">${time}</div>
                    </div>
                `;
                container.appendChild(alertDiv);
            });
        }
        
        // 控制函数
        function refreshSensorData() {
            updateSensorData();
            showNotification('数据已刷新', 'success');
        }
        
        function toggleAutoIrrigation() {
            autoIrrigation = !autoIrrigation;
            
            fetch('/api/set-auto-irrigation', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ enabled: autoIrrigation })
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    document.getElementById('auto-btn-text').textContent = 
                        autoIrrigation ? '自动模式' : '手动模式';
                    document.getElementById('auto-btn-icon').textContent = 
                        autoIrrigation ? '🔄' : '🔧';
                    showNotification(data.message, 'success');
                }
            });
        }
        
        function updateThreshold(value) {
            document.getElementById('threshold-value').textContent = value + '%';
            
            fetch('/api/set-auto-irrigation', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ enabled: autoIrrigation, threshold: parseFloat(value) })
            });
        }
        
        function toggleZone(zoneId, start) {
            const action = start ? 'start' : 'stop';
            
            fetch('/api/control-irrigation', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ zone_id: zoneId, action: action })
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showNotification(data.message, 'success');
                    updateSystemStatus();
                }
            });
        }
        
        function runAIAnalysis() {
            const btn = document.getElementById('ai-btn-text');
            const icon = document.getElementById('ai-btn-icon');
            
            btn.textContent = '分析中...';
            icon.innerHTML = '<div class="loading"></div>';
            
            fetch('/api/run-ai-analysis', { method: 'POST' })
                .then(response => response.json())
                .then(data => {
                    setTimeout(() => {
                        btn.textContent = '执行分析';
                        icon.textContent = '🔍';
                        updateSystemStatus();
                        showNotification('AI分析完成', 'success');
                    }, 2000);
                });
        }
        
        function refreshDeviceStatus() {
            updateSystemStatus();
            showNotification('设备状态已更新', 'success');
        }
        
        function clearAlerts() {
            fetch('/api/clear-alerts', { method: 'POST' })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        document.getElementById('alerts-display').innerHTML = 
                            '<div style="text-align: center; color: #666; padding: 20px;">暂无警报</div>';
                        showNotification('警报已清空', 'success');
                    }
                });
        }
        
        function exportData() {
            fetch('/api/export-data')
                .then(response => response.blob())
                .then(blob => {
                    const url = window.URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = `智慧农业数据_${new Date().toISOString().slice(0,10)}.json`;
                    a.click();
                    window.URL.revokeObjectURL(url);
                    showNotification('数据导出成功', 'success');
                });
        }
        
        // 通知函数
        function showNotification(message, type = 'info') {
            const notification = document.createElement('div');
            notification.style.cssText = `
                position: fixed;
                top: 20px;
                right: 20px;
                background: ${type === 'success' ? '#4CAF50' : '#2196F3'};
                color: white;
                padding: 15px 20px;
                border-radius: 10px;
                box-shadow: 0 4px 20px rgba(0,0,0,0.3);
                z-index: 1000;
                animation: slideIn 0.3s ease;
                font-weight: 500;
            `;
            notification.textContent = message;
            
            document.body.appendChild(notification);
            
            setTimeout(() => {
                notification.style.animation = 'slideOut 0.3s ease';
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 300);
            }, 3000);
        }
        
        // 添加CSS动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes slideIn {
                from { transform: translateX(100%); opacity: 0; }
                to { transform: translateX(0); opacity: 1; }
            }
            @keyframes slideOut {
                from { transform: translateX(0); opacity: 1; }
                to { transform: translateX(100%); opacity: 0; }
            }
        `;
        document.head.appendChild(style);
        
        // 页面离开时清理
        window.addEventListener('beforeunload', () => {
            if (updateInterval) {
                clearInterval(updateInterval);
            }
        });
    </script>
</body>
</html>
"""

# 路由定义
@app.route('/')
def index():
    return render_template_string(HTML_TEMPLATE)

@app.route('/api/current-data')
def get_current_data():
    return jsonify(agricultural_system.get_current_data())

@app.route('/api/historical-data')
def get_historical_data():
    time_scale = request.args.get('time_scale', 'realtime')
    limit = request.args.get('limit', type=int)
    data = agricultural_system.get_historical_data(time_scale, limit)
    return jsonify(data)

@app.route('/api/system-status')
def get_system_status():
    return jsonify(agricultural_system.get_system_status())

@app.route('/api/control-irrigation', methods=['POST'])
def control_irrigation():
    data = request.get_json()
    result = agricultural_system.control_irrigation(data['zone_id'], data['action'])
    return jsonify(result)

@app.route('/api/set-auto-irrigation', methods=['POST'])
def set_auto_irrigation():
    data = request.get_json()
    result = agricultural_system.set_auto_irrigation(
        data['enabled'], 
        data.get('threshold')
    )
    return jsonify(result)

@app.route('/api/run-ai-analysis', methods=['POST'])
def run_ai_analysis():
    # 触发AI分析更新
    agricultural_system._update_ai_analysis()
    return jsonify({'success': True, 'message': 'AI分析已完成'})

@app.route('/api/clear-alerts', methods=['POST'])
def clear_alerts():
    agricultural_system.alerts.clear()
    return jsonify({'success': True, 'message': '警报已清空'})

@app.route('/api/export-data')
def export_data():
    """导出数据"""
    export_data = {
        'timestamp': datetime.now().isoformat(),
        'current_data': agricultural_system.get_current_data(),
        'historical_data': {
            'realtime': list(agricultural_system.realtime_data),
            'hourly': list(agricultural_system.hourly_data),
            'daily': list(agricultural_system.daily_data)
        },
        'system_status': agricultural_system.get_system_status()
    }
    
    from flask import Response
    return Response(
        json.dumps(export_data, indent=2, ensure_ascii=False),
        mimetype='application/json',
        headers={'Content-Disposition': 'attachment; filename=agricultural_data.json'}
    )

def main():
    """主函数"""
    # 找到可用端口
    port = find_available_port()
    
    print("🌱 智慧农业边缘控制系统 - Web完整演示版")
    print("=" * 60)
    print(f"🚀 系统启动成功")
    print(f"📡 传感器模拟器: 已激活 (15种传感器)")
    print(f"💧 智能灌溉系统: 已就绪 (4个灌溉区域)")
    print(f"🤖 AI分析引擎: 已加载")
    print(f"📊 实时数据可视化: 已启用")
    print(f"🌐 Web服务器端口: {port}")
    print(f"🔗 访问地址: http://localhost:{port}")
    print(f"📱 移动端访问: http://192.168.x.x:{port}")
    print("✨ 功能特色:")
    print("   • 15种环境传感器实时监控")
    print("   • 智能灌溉自动控制系统")
    print("   • AI病虫害风险评估")
    print("   • 多维度数据趋势分析")
    print("   • 设备状态实时监控")
    print("   • 智能警报和通知系统")
    print("🔧 按 Ctrl+C 停止服务")
    print("=" * 60)
    
    try:
        app.run(host='0.0.0.0', port=port, debug=False, threaded=True)
    except KeyboardInterrupt:
        print("\n🛑 系统已停止")
        agricultural_system.running = False

if __name__ == "__main__":
    main()